////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Michiel Helvensteijn                                    //
//                                                                            //
// This file is part of the Mist compiler.                                    //
//                                                                            //
// The Mist compiler is free software: you can redistribute it and/or modif   //
// it under the terms of the GNU General Public License as published by       //
// the Free Software Foundation, either version 3 of the License, or          //
// (at your option) any later version.                                        //
//                                                                            //
// The Mist compiler is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of             //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              //
// GNU General Public License for more details.                               //
//                                                                            //
// You should have received a copy of the GNU General Public License          //
// along with the Mist compiler.  If not, see <http://www.gnu.org/licenses/>. //
////////////////////////////////////////////////////////////////////////////////

/******************************************************************************
 * Includes                                                                   *
 ******************************************************************************/

#include <boost/filesystem.hpp>
namespace bf = ::boost::filesystem;

#include <boost/progress.hpp>
using boost::progress_display;

#include <set>
using std::set;

using std::pair;
using std::cout;

#include "visitors/echovisitor.hpp"
#include "visitors/astvisitor.hpp"
#include "codelocation.hpp"
#include "compilerfixture.hpp"

/******************************************************************************
 * Test Cases                                                                 *
 ******************************************************************************/

BOOST_AUTO_TEST_SUITE( suite_compiler )
	
	BOOST_FIXTURE_TEST_CASE( test_success, CompilerFixture ) {
		set<TestCase> testCases = find_test_cases("test/success");
		start_progress_bar(testCases.size());
		foreach (TestCase testCase, testCases) {
			setup(testCase.fileBase);
			
			string baseMessage = testCase.fileBase + ": ";
			
			CHECK( messages()->count() == 0u , baseMessage + "compiler errors" );
			if (messages()->count() > 0u) {
				progress();
				continue;
			}
			
			string echoDiff    = diff("echo"   , echo       (tree(), 4));
			string astDiff     = diff("ast"    , ast        (tree()   ));
			string symbolsDiff = diff("symbols", symboltable(tree()   ));
			CHECK( echoDiff.empty()    , baseMessage + "echo:\n\n"        + echoDiff    );
			CHECK( astDiff.empty()     , baseMessage + "ast:\n\n"         + astDiff     );
			CHECK( symbolsDiff.empty() , baseMessage + "symboltable:\n\n" + symbolsDiff );
			
			string compileErrors = compile();
			CHECK( compileErrors.empty() , baseMessage + "g++ errors:\n\n" + compileErrors );
			if (!compileErrors.empty()) {
				progress();
				continue;
			}
			
			foreach (string run, testCase.runs) {
				pair<string, string> diff = run_diff(file_base(), file_base() + "." + run + ".in", file_base() + "." + run + ".out");
				CHECK( diff.second.empty() , baseMessage + "assertion failure:\n\n" + diff.second );
				CHECK( diff.first.empty()  , baseMessage + "wrong output:\n\n" + diff.first );
			}
			
			remove();
			
			progress();
		}
	}
	
BOOST_AUTO_TEST_SUITE_END()
